/*	COMP 6761 Assignment 1 Framework
	Created by Kaustubha Mendhurwar on 09/09/14.
	Copyright (c) 2014 Concordia University. All rights reserved.
*/

#include "Model.h"
#include "World.h"
#include "Renderer.h"
#include "Camera.h"
#include "EventManager.h"

#include <GLFW/glfw3.h>

using namespace std;
using namespace glm;

World::World()
	:
	mCamera(new Camera(vec3(0.0f, 0.0f, 10.0f))),
	mModel(new Model("../Source/Models/cube.obj")),
#ifndef OPENGL33
	tesselationShader(new Shader(
		"../Source/ShadersOpenGL43/step01.vertexshader", 
		"../Source/ShadersOpenGL43/step02.tessellationcontrolshader", 
		"../Source/ShadersOpenGL43/step03.tessellationvaluationshader", 
		"../Source/ShadersOpenGL43/step04.geometryshader",
		"../Source/ShadersOpenGL43/step05.fragmentshader"))
#else
		tesselationShader(new Shader(
		"../Source/ShadersOpenGL33/step01.vertexshader",
		"../Source/ShadersOpenGL33/step02.geometryshader",
		"../Source/ShadersOpenGL33/step03.fragmentshader"))
#endif
{
//    worldMatrix = mModel->GetWorldMatrix();
}

World::~World()
{

}
	
void World::Update(float dt)
{
	// Update current Camera
	mCamera->Update(dt);

	// Update models
	mModel->Update(dt);	
}

void World::Draw()
{
	//Renderer::BeginFrame();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	// Set Shader... In a more sofisticated application, each model could use a different shader
	// In our case, all the models use a common shader

	tesselationShader->begin();


	
	// Send the view projection constants to the shader
	mat4 VP = mCamera->GetViewProjectionMatrix();
    
//    worldMatrix = ;
    
    glm::mat4 model = mModel->GetWorldMatrix() * worldMatrix * EventManager::GetArcBallRotation();
    

	tesselationShader->setUniformMatrix4v("ViewProjectonTransform", &VP[0][0]);
	tesselationShader->setUniformMatrix4v("WorldTransform", &model[0][0]);
	tesselationShader->setUniform("tesselationInnerLevel", EventManager::tesselationInnerLevel);
	tesselationShader->setUniform("tesselationOuterLevel", EventManager::tesselationOuterLevel);
	//glUniformMatrix4fv(VPMatrixLocation, 1, GL_FALSE, &VP[0][0]);

	if (EventManager::wireframe) {
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	}
	else {
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	}
	tesselationShader->setUniform("DrawInWireframe", EventManager::wireframe);
	// Draw model
	mModel->Draw();
	//tesselationShader->end();
	Renderer::EndFrame();
}

void World::LoadScene()
{
	//mModel.reset(new Model("../Source/Models/cube.obj"));
}
